package org.eclipse.rally.plugin.webservice;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.axis.client.Stub;
import org.eclipse.rally.plugin.views.DashboardGUI;
import org.eclipse.rally.plugin.views.DefectsTabGUI;
import org.eclipse.rally.plugin.views.HeaderPage;
import org.eclipse.rally.plugin.views.TaskTabGUI;
import org.eclipse.rally.plugin.views.TestCaseTabGUI;

import com.rallydev.webservice.v1_12.domain.Attachment;
import com.rallydev.webservice.v1_12.domain.AttachmentContent;
import com.rallydev.webservice.v1_12.domain.Defect;
import com.rallydev.webservice.v1_12.domain.DomainObject;
import com.rallydev.webservice.v1_12.domain.HierarchicalRequirement;
import com.rallydev.webservice.v1_12.domain.Iteration;
import com.rallydev.webservice.v1_12.domain.PersistableObject;
import com.rallydev.webservice.v1_12.domain.Project;
import com.rallydev.webservice.v1_12.domain.QueryResult;
import com.rallydev.webservice.v1_12.domain.Release;
import com.rallydev.webservice.v1_12.domain.Task;
import com.rallydev.webservice.v1_12.domain.TestCase;
import com.rallydev.webservice.v1_12.domain.User;
import com.rallydev.webservice.v1_12.domain.WSObject;
import com.rallydev.webservice.v1_12.service.RallyService;
import com.rallydev.webservice.v1_12.service.RallyServiceServiceLocator;

public class RallyMain {
	
	public static RallyService service = null;
	public static final String rallyUrl = "https://rally1.rallydev.com/slm/webservice/1.12/rallyservice";
	
	
	public List<WSObject> searchObject(WSObject wsObject,String className,int minPageVal,int maxPagVal){
    	List<WSObject> lstWsObject = new ArrayList<WSObject>();
    	String queryString = createQuery(wsObject,className);
    	try{
    	if(service != null){
    		QueryResult queryResult = service.query(null, className, queryString,"", true, minPageVal, maxPagVal);
    		if(!publishErrors(queryResult)){
    			setTotalObjectSize(queryResult,className);
    			lstWsObject = generateSearchResult(queryResult,service);
    		}
		 }
    	}catch(Exception e){
    		System.out.println("Exception in createQuery "+e);
    	}
    	return lstWsObject;
    }
	
	public List<WSObject> searchObject(WSObject wsObject,String className){
    	List<WSObject> lstWsObject = new ArrayList<WSObject>();
    	String queryString = createQuery(wsObject,className);
    	try{
    	if(service != null){
    		QueryResult queryResult = service.query(null, className, queryString,"", true, 1, 1);
    		if(!publishErrors(queryResult)){
    		lstWsObject = searchObject(wsObject,className,1,queryResult.getTotalResultCount().intValue());
    		}
    		}
    	}catch(Exception e){
    		System.out.println("Exception in createQuery "+e);
    	}
    	return lstWsObject;
    }
	
	
	private void setTotalObjectSize(QueryResult queryResult,String className){
		int totObjCount  = queryResult.getTotalResultCount().intValue();
		if(className.equalsIgnoreCase("Defect")){
			DefectsTabGUI.totalDefects = totObjCount;
			DashboardGUI.totalDefects = totObjCount;
		}else if(className.equalsIgnoreCase("Task")){
			TaskTabGUI.totalTasks = totObjCount;
			DashboardGUI.totalTasks = totObjCount;
		}else if(className.equalsIgnoreCase("TestCase")){
			TestCaseTabGUI.totaltestCases = totObjCount;
			DashboardGUI.totalTests = totObjCount;
		}
		
	}
	
	public static List listUsers(){
		RallyMain main = new RallyMain();
		return main.searchObject(new User(),"User");
		
	}
	
    public List listIteration(){
		
		return searchObject(new Iteration(),"Iteration");
		
	}
    
	
    public static WSObject readDefectObject(String defectRefrence){
    	WSObject wsObject = null;	
  	  try{
  			Defect defect	= new Defect(); 
  			defect.setRef(defectRefrence);
  			wsObject =  service.read(defect);
  		
  	  }catch(Exception e){
  		  System.out.println("Exception in readDefectObject "+e);
  		  return null;
  	  }
  	return wsObject;	
  	}
    
    public static WSObject readAttachemntObject(String attachemntRefrence){
    	WSObject wsObject = null;	
  	  try{
  		Attachment attachemnt	= new Attachment(); 
  		attachemnt.setRef(attachemntRefrence);
  			wsObject =  service.read(attachemnt);
  		
  	  }catch(Exception e){
  		  System.out.println("Exception in readDefectObject "+e);
  		  return null;
  	  }
  	return wsObject;	
  	}
    
    public static WSObject readAttachemntContentObject(String attachemntContentRefrence){
    	WSObject wsObject = null;	
  	  try{
  		AttachmentContent attachemntContent	= new AttachmentContent(); 
  		attachemntContent.setRef(attachemntContentRefrence);
  			wsObject =  service.read(attachemntContent);
  		
  	  }catch(Exception e){
  		  System.out.println("Exception in readDefectObject "+e);
  		  return null;
  	  }
  	return wsObject;	
  	}
    
    public static WSObject readRelease(String releaseRefrence){
    	WSObject wsObject = null;	
  	  try{
  		Release release	= new Release(); 
  		release.setRef(releaseRefrence);
  			wsObject =  service.read(release);
  		
  	  }catch(Exception e){
  		  System.out.println("Exception in readDefectObject "+e);
  		  return null;
  	  }
  	return wsObject;	
  	}
    
    
    public static WSObject readIteration(String iterationRefrence){
    	WSObject wsObject = null;	
  	  try{
  		Iteration iteration	= new Iteration(); 
  		iteration.setRef(iterationRefrence);
  			wsObject =  service.read(iteration);
  		
  	  }catch(Exception e){
  		  System.out.println("Exception in readDefectObject "+e);
  		  return null;
  	  }
  	return wsObject;	
  	}
    
    public static WSObject readProject(String projectRefrence){
    	WSObject wsObject = null;	
  	  try{
  		Project project	= new Project(); 
  		project.setRef(projectRefrence);
  			wsObject =  service.read(project);
  		
  	  }catch(Exception e){
  		  System.out.println("Exception in readDefectObject "+e);
  		  return null;
  	  }
  	return wsObject;	
  	}
    
    
    public static WSObject readUserStory(String userStoryRefrence){
    	WSObject wsObject = null;	
  	  try{
  		HierarchicalRequirement userStory	= new HierarchicalRequirement(); 
  		userStory.setRef(userStoryRefrence);
  			wsObject =  service.read(userStory);
  		
  	  }catch(Exception e){
  		  System.out.println("Exception in readDefectObject "+e);
  		  return null;
  	  }
  	return wsObject;	
  	}
    
	public static void updateObject(PersistableObject rallyObject){
	  try{
		  System.out.println("in updateObject=="+rallyObject);
	  service.update(rallyObject);
	  }catch(Exception e){
		  System.out.println("Exception in updateObject "+e);
	  }
	}
	
	public void deleteObject(PersistableObject rallyObject,String className){
		  try{
		  service.delete(rallyObject);
		  }catch(Exception e){
			  System.out.println("Exception in updateObject "+e);
		  }
	}
	
	public void createObject(PersistableObject rallyObject,String className){
		  try{
		  service.create(rallyObject);
		  }catch(Exception e){
			  System.out.println("Exception in updateObject "+e);
		  }
	}
	
	private String createQuery(WSObject wsObject,String className){
		String searchQuery = "";
		if(className.equalsIgnoreCase("Defect")){
			Defect defect =(Defect)wsObject;
			searchQuery = createDefectQuery(defect);
		}else if(className.equalsIgnoreCase("Task")){
			Task test =(Task)wsObject;
			searchQuery = createTaskQuery(test);
		}else if(className.equalsIgnoreCase("TestCase")){
			TestCase testCase =(TestCase)wsObject;
			searchQuery = createTestCaseQuery(testCase);
		}else if(className.equalsIgnoreCase("HierarchicalRequirement")){
			 HierarchicalRequirement userstory = (HierarchicalRequirement)wsObject;
			searchQuery = createUserStoryQuery(userstory);
		}else if(className.equalsIgnoreCase("Iteration")){
			searchQuery = "";
		}
	  return searchQuery;	
	}
	
	private String createDefectQuery(Defect defect) {
    	String searchQuery = "";
    	int count = 0;
    	if(defect != null){
    		if(defect.getFormattedID() != null){
    			searchQuery += "(FormattedID = \""+defect.getFormattedID()+"\")*";
    		}
    		if(defect.getSeverity() != null){
    			
    			searchQuery += "(Severity = \""+defect.getSeverity()+"\")*";
    		
    		}
    		if(defect.getPriority() != null){
    			
    			searchQuery += "(Priority = \""+defect.getPriority()+"\")*";
    			
    		}
    		if(defect.getState() != null){
    			String tempSearchQuery = "";
    			String defectState = defect.getState();
    			if(defectState.contains(",")){
    				StringTokenizer str = new StringTokenizer(defectState,",");
    				int tokenCount = str.countTokens();
    				
;    				int i=0;
    				 while(str.hasMoreTokens()){
    					 i++;   
    					 if(i >= 2){
    						 String temp =  " ( "+tempSearchQuery +"(State = \""+str.nextToken()+"\" ) )";
    						 tempSearchQuery = temp;
    					 }else
    					 tempSearchQuery += "(State = \""+str.nextToken()+"\" )";
    				 if(i < tokenCount){
    					 tempSearchQuery += " OR ";
    				 }
    					
    				}
    				 searchQuery += tempSearchQuery+"*";
    			}else{
    			searchQuery += "(State = \""+defect.getState()+"\")*";
    			}
    		}
    		if(defect.getTargetBuild() != null){
    			
    			searchQuery += "(TargetBuild = \""+defect.getTargetBuild()+"\")*";
    			
    		}
    		if(defect.getFixedInBuild() != null){
    			
    			searchQuery += "(FixedInBuild = \""+defect.getFixedInBuild()+"\")*";
    			
    		}
    		if(defect.getSubmittedBy() != null){
    			
    			searchQuery += "(SubmittedBy = \""+defect.getSubmittedBy()+"\")*";
    			
    		}
    		if(defect.getOwner() != null){
    			
    			searchQuery += "(Owner = \""+defect.getOwner()+"\")*";
    		
    		}
    	}else{
    		searchQuery = null;
    	}
    	
    	return generateQuery(searchQuery);
    }
	
	public String generateQuery(String searchQuery){
		ArrayList list = new ArrayList();
		StringTokenizer str = new StringTokenizer(searchQuery,"*");
		while(str.hasMoreTokens()){
			String strTocken = str.nextToken();
			list.add(strTocken.replace("*", ""));
		}
		String S2 = "";
		String S1 = "";
		int k =0;
		int l = 0;
		for(int i=0;i<list.size();i++){
			String S3 = "";
			S3 = (String)list.get(i);
			int j = i+1;
				if(j%2 == 0){
					if(i != (list.size()-1)){
						k++;
					System.out.println("k=="+k);
					if(k >= 2){
					  String temp = " ( "+S1+"( "+S2+S3+" ) )";
					  temp += " AND ";
					  S1 = temp;
					}else					 
					 S1 += "( "+S2+S3+" ) And ";
				   	l++;
					}else{
						System.out.println("l=="+l);
						if(l > 0)
					     S1 += "( "+S2+S3+" ) ";
						else
							S1 += S2+S3;
					}
					S2 = "";
				}else{
				if(i != (list.size()-1)){
				    S3 += " AND " ;
				}else{
					S1 += S3;
				}
					
				  S2 += S3;	
				}
				
				
		}
		
		
		if(list.size() > 1){
			System.out.println("S1=="+S1);
		 return "( "+S1+" )";
		}else{
			System.out.println("S1=="+S1);
		 return S1;
		}
	}
	
	private String createTaskQuery(Task task) {
    	String searchQuery = "";
    	if(task != null){
    		if(task.getFormattedID() != null){
    			
    			searchQuery += "(FormattedID = \""+task.getFormattedID()+"\")*";
    			
    		}
    		if(task.getRelease() != null){
    		
    			searchQuery += "(Release = \""+task.getRelease()+"\")*";
    			
    		}
    		if(task.getIteration() != null){
    			
    			searchQuery += "(Iteration = \""+task.getIteration()+"\")*";
    			
    		}
    		if(task.getState() != null){
    			
    			searchQuery += "(State = \""+task.getState()+"\")*";
    			
    		}
    		if(task.getOwner() != null){
    			
    			searchQuery += "(Owner = \""+task.getOwner()+"\")*";
    			
    		}
    	}else{
    		searchQuery = null;
    	}
    	return generateQuery(searchQuery);
    }
	
private String createTestCaseQuery(TestCase testcase) {
    	String searchQuery = "";
    	
    	if(testcase != null){
    		if(testcase.getFormattedID() != null){
    			searchQuery += "(FormattedID = \""+testcase.getFormattedID()+"\")*";
    			
    		}
    		if(testcase.getType() != null){
    		
    			searchQuery += "(Type = \""+testcase.getType()+"\")*";
    			
    		}
    	
    		if(testcase.getPriority() != null){
    			
    			searchQuery += "(Priority = \""+testcase.getPriority()+"\")*";
    		
    		}
    		if(testcase.getOwner() != null){
    			 
    			searchQuery += "(Owner = \""+testcase.getOwner()+"\")*";
    			
    		}
    		if(testcase.getMethod() != null){
    		
    			searchQuery += "(Method = \""+testcase.getMethod()+"\")*";
    			
    		}
    		if(testcase.getLastVerdict() != null){
    			
    			searchQuery += "(LastVerdict = \""+testcase.getLastVerdict()+"\")*";
    			
    		}
    		if(testcase.get_package() != null){
    		
    			searchQuery += "(_package = \""+testcase.get_package()+"\")*";
    			
    		}
    	}else{
    		searchQuery = null;
    	}
    	System.out.println("searchQuery=="+searchQuery);
    	return generateQuery(searchQuery);
    }

private String createUserStoryQuery(HierarchicalRequirement userstory) {
	String searchQuery = "";
	
	if(userstory != null){
		if(userstory.getFormattedID() != null){
			searchQuery += "(FormattedID = \""+userstory.getFormattedID()+"\")*";
			
		}
		if(userstory.getType() != null){
		
			searchQuery += "(Type = \""+userstory.getType()+"\")*";
			
		}
	
		
		if(userstory.getOwner() != null){
			 
			searchQuery += "(Owner = \""+userstory.getOwner()+"\")*";
			
		}
		
		if(userstory.get_package() != null){
		
			searchQuery += "(_package = \""+userstory.get_package()+"\")*";
			
		}
	}else{
		searchQuery = null;
	}
	System.out.println("searchQuery for User Story  =="+searchQuery);
	return generateQuery(searchQuery);
}



	private boolean publishErrors(QueryResult queryResult){
	    	boolean status = false;
	    	if(queryResult.getErrors().length>0){   
	        status = true;
	    	for(int i=0; i<queryResult.getErrors().length;i++){  	 
	   		 System.out.println(queryResult.getErrors()[i]); 
	   		 }
	     }
	    	return status;
	    }
	    
	private List<WSObject> generateDetailedSearchResult(QueryResult queryResult,RallyService service){
	    	List<WSObject> lstWsObject = new ArrayList<WSObject>();
	    	try{
	    	DomainObject[] domainObjects = queryResult.getResults();
			 if(domainObjects!=null && domainObjects.length>0){ 
		    	 for(int i=0;i<domainObjects.length;i++){   
		    		 WSObject wsObject = new WSObject();
		    		 wsObject =  service.read(domainObjects[i]);
		    		 System.out.println("wsObject=="+wsObject);
		    		 lstWsObject.add(wsObject);
		    	 }
			 }
			
	    	}catch(Exception e){
	    		System.out.println("Exception in generateSearchResult "+e);
	    	}
	    	return lstWsObject;
	    }
	
	
	private List<WSObject> generateSearchResult(QueryResult queryResult,RallyService service){
    	List<WSObject> lstWsObject = new ArrayList<WSObject>();
    	try{
    	DomainObject[] domainObjects = queryResult.getResults();
		 if(domainObjects!=null && domainObjects.length>0){ 
	    	 for(int i=0;i<domainObjects.length;i++){   
	    		 WSObject wsObject = (WSObject) domainObjects[i];
	    		 lstWsObject.add(wsObject);
	    	 }
		 }
		
    	}catch(Exception e){
    		System.out.println("Exception in generateSearchResult "+e);
    	}
    	return lstWsObject;
    }
	 
	public static boolean validateUserLogin(String userName, String password){
		boolean loginSuccess = false;
		try {
			   System.out.println("Rally, UN ="+userName+"::: PWD ="+password);
		       URL url = new URL(rallyUrl);
			   service = (new RallyServiceServiceLocator()).getRallyService(url);
		       Stub stub = (Stub)service;// set authentication information on the service
		       stub.setUsername(userName);
		       stub.setPassword(password);
			   stub.setMaintainSession(true);// Configure the service to maintain an HTTP session cookie
			   System.out.println("Current User :"+service.getCurrentUser().getRefObjectName());
			   if(service.getCurrentUser().getRefObjectName() != null){
				   loginSuccess = true;
				   HeaderPage.userNameFromRally = service.getCurrentUser().getRefObjectName();
				   HeaderPage.userEmailFromRally =  userName ;
			   }
	        }catch(Exception e){
	        	System.out.println("Exception in validateUserLogin Service Generation : "+e);
	        	e.printStackTrace();
	        	return loginSuccess;
	    	}
		return loginSuccess;
	}
	    
	public static RallyService getService() {
		return service;
	}
	public static WSObject readTaskObject(String taskRefrence){
		WSObject wsObject = null;	
  	  try{
  		  Task task	= new Task(); 
  			task.setRef(taskRefrence);
  			wsObject =  service.read(task);
  		
  	  }catch(Exception e){
  		  System.out.println("Exception in readTaskObject "+e);
  		  return null;
  	  }
  	return wsObject;	
  	}
	public static WSObject readTaskWorkProdObject(String strRef) {
		
		WSObject wsObject = null;	
		try {

			HierarchicalRequirement hr = new HierarchicalRequirement();
			hr.setRef(strRef);
			wsObject = service.read(hr);

		} catch (Exception e) {
			System.out.println("Exception in readWorkProdObject " + e);
			return null;
		}
		return wsObject;
	}

}
